# 作者:龙炜轩,探索matplotlib饼图的极限！！
#！ 教学用多字图绘制脚本
# 这个脚本可以解决什么问题？
# 解决线条样式选择困难症 + 单独绘制效率慢
# import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from numpy.random.mtrand import randint  # 从numpy.random.mtrand模块导入randint函数，用于生成随机整数

# 定义一个子图绘制类
class SubpieImage:
    def __init__(self, x, ys, suptitle):
        self.x = x
        self.ys = ys
        self.suptitle = suptitle
    
    def subpieImage(self):
        '''绘制多子图上的图像'''

        # 超过六张子图时，需要手动调整子图布局
        if len(self.ys) > 6:
            plt.subplots_adjust(hspace=0.5)
        
        # 十张子图退出
        if len(self.ys) > 10:
            print("最多只能绘制10张子图")
            return

        # 初始化已用样式列表
        usedStyles = []
        plt.rcParams['font.sans-serif'] = ['SimHei']    
        plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
        plt.suptitle(self.suptitle)
        
        for i in range(len(self.ys)):  # 几个测试用例函数就循环几次
            plt.subplot(2, 2, i+1)
            
            # 令颜色随机（10中线条样式）
            lineStyles = ['ko--', 'r--', 'go--', 'b-', 'm*-', 'c^--', 'y*-', 'k.-', 'rs-', 'bp--', 'g^-']

            # 用条件语句判断是否重复选用相同样式，如相同则重新搜索新样式，循环往复。
            style = lineStyles[randint(0, len(lineStyles))]  # 区间内随机索引一个样式
            
            # 检查样式是否被选用过，如是则随机搜索直至新样式，循环往复。
            while style in usedStyles:
                style = lineStyles[randint(0, len(lineStyles))]
            
            usedStyles.append(style)
            colors = plt.get_cmap('Blues')(np.linspace(0.2, 0.7, len(x)))
            plt.pie(self.x, self.ys[i], style, label=f"f$y{i+1}$",colors=colors)  # 令标签打印函数名
            plt.title(f"y{i+1}")
            plt.legend()
            
            # 绘制网格
            plt.grid()
        
        plt.show()
    
# 2. 定义函数
'''该变量用于记录选用过的线条样式，下次不再选用'''

def subpieImage(ys, suptitle):
    '''绘制多子图上的图像'''

    # 超过六张子图时，需要手动调整子图布局
    if len(ys) > 6:
        plt.subplots_adjust(hspace=0.5)
    
    # 十张子图退出
    if len(ys) > 10:
        print("最多只能绘制10张子图")
        return

    # 初始化已用样式列表
    usedStyles = []
    plt.rcParams['font.sans-serif'] = ['SimHei']    
    plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
    plt.suptitle(suptitle)

    # 两道检查检查
    assert isinstance(ys,list),"传入的数字不是list结构"
    if isinstance(ys,list):
        print("传入的数字是list结构")
    else:
        print("传入的数字不是list结构")

    for i in range(len(ys)):  # 几个测试用例函数就循环几次
        # 控制画布大小
        # plt.figure(figsize=(40, 24))
        # 控制子图大小
        plt.subplots_adjust(wspace=0.9, hspace=0.9)
        plt.subplot(2, 2, i+1)
        
        # 令颜色随机（10中线条样式）
        lineStyles = ['ko--', 'r--', 'go--', 'b-', 'm*-', 'c^--', 'y*-', 'k.-', 'rs-', 'bp--', 'g^-']

        # 用条件语句判断是否重复选用相同样式，如相同则重新搜索新样式，循环往复。
        style = lineStyles[randint(0, len(lineStyles))]  # 区间内随机索引一个样式
        
        # 检查样式是否被选用过，如是则随机搜索直至新样式，循环往复。
        while style in usedStyles:
            style = lineStyles[randint(0, len(lineStyles))]
        
        usedStyles.append(style)
        colors = plt.get_cmap('Greys_r')(np.linspace(0,1, len(x)))
        plt.pie(ys[i],colors=colors)  # 令标签打印函数名,pie not exist albel args?
        plt.title(f"y{i+1}")
        plt.legend()
        
        # 绘制网格
        plt.grid()
    
    plt.show()

# 3. 主流程
if __name__ == "__main__":
    # 1. 声明
    # 定义一个恒定的x轴数据
    x = np.arange(0, 10, 1, dtype=np.int16)

    # 绘制多子图上的超级标题(非必要)
    # 中文标题需要设置字体

    # 定义3个y轴数据，作为测试数据集，爆炸效果
    y1 = [i for i in range(10,50,10)] 
    y2 = [30,30,30,30]
    y3 = [30 * i for i in range(4)] 
    
    # 统一存进复杂数据结构内方便访问
    ys = [y1, y2, y3]
    a = subpieImage(ys,"test")
    a.subpieImage()